import * as React from 'react';
import { forwardRef, useRef, useEffect, useState } from 'react';
import './index.scss';
import * as echarts from "echarts/core";
import { PieChart } from 'echarts/charts';
import { TitleComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
import 'echarts-gl';
// Register the components needed
echarts.use([TitleComponent, PieChart, CanvasRenderer]);
// 确保createElement可用
const { createElement } = React;

export interface DirectionCountProps {
  /**
   * 方向文字
   */
  direction?: string;

  /**
   * 数量值
   */
  count?: number | string;

  /**
   * 单位
   */
  unit?: string;

  /**
   * 文字颜色
   */
  directionColor?: string;

  /**
   * 背景渐变色
   */
  backgroundColor?: string[];

  /**
   * 间距
   */
  spacing?: number;

  /**
   * 文字大小
   */
  countFontSize?: number;

  /**
   * 点击事件
   */
  onClick?: () => void;

  /**
   * 自定义样式
   */
  style?: React.CSSProperties;

  /**
   * 自定义类名
   */
  className?: string;

  /**
   * 宽度
   */
  width?: number | string;

  /**
   * 高度
   */
  height?: number | string;

  /**
   * 颜色方案
   */
  colorScheme?: string[];

  /**
   * 图表数据
   */
  data?: Array<{
    name: string;
    value: number;
    itemStyle?: {
      color?: string;
      opacity?: number;
    };
  }>;

  /**
   * 是否显示图标
   */
  showIcon?: boolean;

  /**
   * 操作图标
   */
  actionIcon?: string;

  // 低代码平台相关属性（不会传递到DOM）
  __designMode?: string;
  componentId?: string;
  forwardRef?: any;
}

const DirectionCount = forwardRef<HTMLDivElement, DirectionCountProps>((props, ref) => {
  const {
    direction = '西',
    count = 844,
    unit = '个',
    width,
    height,
    colorScheme,
    data = [],
    showIcon,
    actionIcon = 'http://localhost:8085/static/images/qixiangfangzhai/bz9.png',
    onClick,
    style = {},
    className = '',
    ...otherProps
  } = props;
  const componentStyle: React.CSSProperties = {
    width: `100%`,
    height: `100%`,
    ...style
  };
  const handleClick = () => {
    if (onClick) {
      onClick();
    }
  };

  // 用于引用 ECharts 渲染的 DOM 容器
  const chartContainerRef = useRef<HTMLDivElement>(null);
  // 用于存储 ECharts 实例
  const chartInstanceRef = useRef<echarts.ECharts | null>(null);
  // 用于存储当前的 ECharts option，供事件监听器使用
  const currentOptionRef = useRef<any>({});
  const [hoveredData, setHoveredData] = useState<{name: string, value: number} | null>(null); // 当前高亮数据
  const optionData = data && data.length > 0 ? data : [];
  useEffect(() => {
    if (!chartContainerRef.current) {
      return;
    }
    // 如果 ECharts 实例不存在，则初始化它
    if (!chartInstanceRef.current) {
      chartInstanceRef.current = echarts.init(chartContainerRef.current);
    }
    const myChart = chartInstanceRef.current;

    // 构建 3D 饼状图的 option
    const pie3DOption = getPie3D(optionData, 0.8);

    // --- START: 默认高亮第一条数据 ---
    if (pie3DOption.series && pie3DOption.series.length > 0 && optionData.length > 0) {
      setHoveredData({name: optionData[0].name, value: optionData[0].value})
      console.log(optionData[0])
      const firstIndex = 0; // 默认高亮那一条数据，这边默认第一条
      const firstSeries = pie3DOption.series[firstIndex];
      if (firstSeries) {
        firstSeries.pieStatus.hovered = true; // 设置为高亮状态
        // firstSeries.pieData.value += 5
        // 重新计算最后一个扇形的参数方程，使其显示高亮效果
        firstSeries.parametricEquation = getParametricEquation(
          firstSeries.pieData.startRatio,
          firstSeries.pieData.endRatio,
          firstSeries.pieStatus.selected,
          firstSeries.pieStatus.hovered, // 传入 true 表示高亮
          firstSeries.pieStatus.k,
          firstSeries.pieData.value, // 高亮时增加高度
        );
      }
    }

    //是否需要label指引线，如果要就添加一个透明的2d饼状图并调整角度使得labelLine和3d的饼状图对齐，并再次setOption
    pie3DOption.series.push({
      name: 'pie2d',
      type: 'pie',
      startAngle: 90, //起始角度，支持范围[0, 360]。
      clockwise: true, //饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
      radius: ['50%', '90%'],
      center: ['15%', '45%'],
      data: optionData,
      itemStyle: {
        // 隐藏2d饼图图形
        opacity: 0,
      },
      // 隐藏标签，延伸线条显示数字
      label: {
        show: false,
      }
    });
    // 将完整的 option 存储到 ref 中，以便事件监听器可以访问到最新的配置
    currentOptionRef.current = pie3DOption;
    // 设置图表 option
    myChart.setOption(currentOptionRef.current);
    // 确保图表调整大小以填充其容器
    myChart.resize();
    // myChart.setOption(option.current);
    bindListen(myChart, currentOptionRef, optionData.length - 1); // 传入最后一条数据的索引
    // 添加窗口大小调整监听器，使图表响应式
    const handleResize = () => {
      myChart.resize();
    };
    window.addEventListener('resize', handleResize);
    // 清理函数：在组件卸载时销毁图表实例并移除事件监听器
    return () => {
      window.removeEventListener('resize', handleResize);
      myChart.dispose();
      chartInstanceRef.current = null; // 清空 ref
    };
  }, [optionData, width, height, colorScheme]);
  const getPie3D = (pieData, internalDiameterRatio) => {
    let series = [];
    let sumValue = 0;
    let startValue = 0;
    let endValue = 0;
    let legendData = [];  //图例
    let legendBfb = [];
    let k = 1 - internalDiameterRatio
    // 为每一个饼图数据，生成一个 series-surface 配置
    for (let i = 0; i < pieData.length; i++) {
      sumValue += pieData[i].value;
      let seriesItem:any = {
        name:
          typeof pieData[i].name === 'undefined'
            ? `series${i}`
            : pieData[i].name,
        type: 'surface',
        parametric: true,
        wireframe: {
          show: false,
        },
        pieData: pieData[i],
        pieStatus: {
          selected: false,
          hovered: false,
          k: k,
        },
        center: ['15%', '45%'],
      };

      if (typeof pieData[i].itemStyle != 'undefined') {
        let itemStyle:any = {};
        typeof pieData[i].itemStyle.color != 'undefined'
          ? (itemStyle.color = pieData[i].itemStyle.color)
          : null;
        typeof pieData[i].itemStyle.opacity != 'undefined'
          ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
          : null;
        seriesItem.itemStyle = itemStyle;
      }
      series.push(seriesItem);
    }
    legendData = []; // 图例
    legendBfb = [];
    for (let i = 0; i < series.length; i++) {
      endValue = startValue + series[i].pieData.value;
      series[i].pieData.startRatio = (i === 0) ? 0 : startValue / sumValue;
      series[i].pieData.endRatio = endValue / sumValue;
      series[i].parametricEquation = getParametricEquation(
        series[i].pieData.startRatio,
        series[i].pieData.endRatio,
        false,
        false,
        k,
        series[i].pieData.value,
      );
      startValue = endValue;
      let bfb = fomatFloat(series[i].pieData.value / sumValue, 4);
      legendData.push({
        name: series[i].name,
        value: '',
      });
      legendBfb.push({
        name: series[i].name,
        value: bfb,
      });
    }
    console.log(series, 'series')
    //  所有扇区高度相等
    let boxHeight = 10; // 直接设置高度为固定值
    // let boxHeight = getHeight3D(series, 10); //通过传参设定3d饼/环的高度, 移除根据value计算高度的逻辑
    // 准备待返回的配置项，把准备好的 legendData、series 传入。
    let option = {
      color: colorScheme,
      legend: {
        data: legendData,
        icon: 'roundRect',
        orient: 'vertical',
        itemHeight: 4,
        itemWidth: 4,
        right: '14%',
        top: 'center',
        itemGap: 10,
        textStyle: {
          fontSize: 10,
          color: 'rgba(255,255,255,0.8)',
        },
        show: true,
        formatter: function (param) {
          let item:any = legendData.filter((item) => item.name == param)[0];
          return `${item.name}  ${item.value}`;
        },
      },
      grid: {
        right: '0',
        containLabel: true
      },
      xAxis3D: {
        min: -1,
        max: 1,
      },
      yAxis3D: {
        min: -1,
        max: 1,
      },
      zAxis3D: {
        min: -1,
        max: 1,
      },
      grid3D: {
        show: false,
        boxHeight: boxHeight, //圆环的高度
        left: '-18%',
        top: '-6%',
        viewControl: {
          alpha: 38, //角度
          distance: 150, //调整视角到主体的距离，类似调整zoom
          rotateSensitivity: 0, //设置为0无法旋转
          zoomSensitivity: 0, //设置为0无法缩放
          panSensitivity: 0, //设置为0无法平移
          autoRotate: false, //自动旋转
        },
      },
      series: series,
    };
    return option;
  };
  const getParametricEquation = (
    startRatio,
    endRatio,
    isSelected,
    isHovered,
    k,
    h,
  ) => {
    // 计算

    let midRatio = (startRatio + endRatio) / 2;
    let startRadian = startRatio * Math.PI * 2;
    let endRadian = endRatio * Math.PI * 2;
    let midRadian = midRatio * Math.PI * 2;
    // 如果只有一个扇形，则不实现选中效果。
    if (startRatio === 0 && endRatio === 1) {
      isSelected = false;
    }
    // 通过扇形内径/外径的值，换算出辅助参数 k（默认值 1/3）
    k = typeof k !== 'undefined' ? k : 1 / 3;
    // 计算选中效果分别在 x 轴、y 轴方向上的位移（未选中，则位移均为 0）
    let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
    let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
    // 计算高亮效果的放大比例（未高亮，则比例为 1）
    let hoverRate = isHovered ? 1.05 : 1;
    // 返回曲面参数方程
    let baseSliceZ = 1; // Height for non-hovered slices
    let hoverSliceZ = 2; // Height for hovered slices
    let bottomZ = -1; // Fixed Z for the bottom of the slice
    const currentTopZ = isHovered ? hoverSliceZ : baseSliceZ;
    return {
      u: {
        min: -Math.PI,
        max: Math.PI * 3,
        step: Math.PI / 32,
      },
      v: {
        min: 0,
        max: Math.PI * 2,
        step: Math.PI / 20,
      },
      x: function (u, v) {
        if (u < startRadian) {
          return (
            offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          );
        }
        if (u > endRadian) {
          return (
            offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          );
        }
        return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
      },
      y: function (u, v) {
        if (u < startRadian) {
          return (
            offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
          );
        }
        if (u > endRadian) {
          return (
            offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
          );
        }
        return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
      },
      z: function (u, v) {
        if (u < -Math.PI * 0.5) {
          return Math.sin(u);
        }
        if (u > Math.PI * 2.5) {
          return Math.sin(u) * currentTopZ;
        }
        return Math.sin(v) > 0 ? currentTopZ : bottomZ;
      },
    };
  };

  const fomatFloat = (num, n) => {
    var f = parseFloat(num);
    if (isNaN(f)) {
      return false;
    }
    f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n); // n 幂
    var s = f.toString();
    var rs = s.indexOf('.');
    //判定如果是整数，增加小数点再补0
    if (rs < 0) {
      rs = s.length;
      s += '.';
    }
    while (s.length <= rs + n) {
      s += '0';
    }
    return s;
  };

  const bindListen = (myChart, optionRef, initialHoveredIndex = 0) => {
    // 监听鼠标事件，实现饼图选中效果（单选），近似实现高亮（放大）效果。
    let selectedIndex = '';
    let hoveredIndex = initialHoveredIndex;
    // 监听点击事件，实现选中效果（单选）
    myChart.on('click', function (params) {
      let options = optionRef.current;
      // 从 option.series 中读取重新渲染扇形所需的参数，将是否选中取反。
      if (options.series[params.seriesIndex].name === 'pie2d') return;
      let isSelected = !options.series[params.seriesIndex].pieStatus.selected;
      let isHovered = options.series[params.seriesIndex].pieStatus.hovered;
      let k = options.series[params.seriesIndex].pieStatus.k;
      let startRatio = options.series[params.seriesIndex].pieData.startRatio;
      let endRatio = options.series[params.seriesIndex].pieData.endRatio;
      // 如果之前选中过其他扇形，将其取消选中（对 options 更新）
      if (selectedIndex !== '' && selectedIndex !== params.seriesIndex) {
        options.series[selectedIndex].parametricEquation =
          getParametricEquation(
            options.series[selectedIndex].pieData.startRatio,
            options.series[selectedIndex].pieData.endRatio,
            false,
            false,
            k,
            options.series[selectedIndex].pieData.value,
          );
        options.series[selectedIndex].pieStatus.selected = false;
      }
      // 对当前点击的扇形，执行选中/取消选中操作（对 options 更新）
      options.series[params.seriesIndex].parametricEquation =
        getParametricEquation(
          startRatio,
          endRatio,
          isSelected,
          isHovered,
          k,
          options.series[params.seriesIndex].pieData.value,
        );
      options.series[params.seriesIndex].pieStatus.selected = isSelected;
      // 如果本次是选中操作，记录上次选中的扇形对应的系列号 seriesIndex
      isSelected ? (selectedIndex = params.seriesIndex) : null;
      // 使用更新后的 option，渲染图表
      myChart.setOption(options);
    });
    // 监听 mouseover，近似实现高亮（放大）效果
    myChart.on('mouseover', function (params) {
      const options = optionRef.current;
      // 准备重新渲染扇形所需的参数
      let isSelected;
      let isHovered;
      let startRatio;
      let endRatio;
      let k;
      // 如果触发 mouseover 的扇形当前已高亮，则不做操作
      if (hoveredIndex === params.seriesIndex) {
        return;
        // 否则进行高亮及必要的取消高亮操作
      } else {
        // 如果当前有高亮的扇形，取消其高亮状态（对 options 更新）
        if (hoveredIndex !== '') {
          // 从 options.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 false。
          isSelected = options.series[hoveredIndex].pieStatus.selected;
          isHovered = false;
          startRatio = options.series[hoveredIndex].pieData.startRatio;
          endRatio = options.series[hoveredIndex].pieData.endRatio;
          k = options.series[hoveredIndex].pieStatus.k;
          // 对当前点击的扇形，执行取消高亮操作（对 options 更新）
          options.series[hoveredIndex].parametricEquation =
            getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              options.series[hoveredIndex].pieData.value,
            );
          options.series[hoveredIndex].pieStatus.hovered = isHovered;
          // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
          hoveredIndex = null;
        }
        // 如果触发 mouseover 的扇形不是透明圆环，将其高亮（对 options 更新）
        if (
          params.seriesName !== 'mouseoutSeries' &&
          params.seriesName !== 'pie2d'
        ) {
          // 从 options.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
          isSelected = options.series[params.seriesIndex].pieStatus.selected;
          isHovered = true;
          startRatio = options.series[params.seriesIndex].pieData.startRatio;
          endRatio = options.series[params.seriesIndex].pieData.endRatio;
          k = options.series[params.seriesIndex].pieStatus.k;
          // 对当前点击的扇形，执行高亮操作（对 options 更新）
          options.series[params.seriesIndex].parametricEquation =
            getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              options.series[params.seriesIndex].pieData.value + 5,
            );
          options.series[params.seriesIndex].pieStatus.hovered = isHovered;
          // 记录上次高亮的扇形对应的系列号 seriesIndex
          hoveredIndex = params.seriesIndex;
        }
        // 使用更新后的 option，渲染图表
        myChart.setOption(options);
      }
    });
    // 修正取消高亮失败的 bug
    myChart.on('globalout', function () {
      const options = optionRef.current;
      // 准备重新渲染扇形所需的参数
      let isSelected;
      let isHovered;
      let startRatio;
      let endRatio;
      let k;
      if (hoveredIndex !== '') {
        // 从 options.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
        isSelected = options.series[hoveredIndex].pieStatus.selected;
        isHovered = false;
        k = options.series[hoveredIndex].pieStatus.k;
        startRatio = options.series[hoveredIndex].pieData.startRatio;
        endRatio = options.series[hoveredIndex].pieData.endRatio;
        // 对当前点击的扇形，执行取消高亮操作（对 options 更新）
        options.series[hoveredIndex].parametricEquation = getParametricEquation(
          startRatio,
          endRatio,
          isSelected,
          isHovered,
          k,
          options.series[hoveredIndex].pieData.value,
        );
        options.series[hoveredIndex].pieStatus.hovered = isHovered;
        // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
        hoveredIndex = null;
      }
      // 使用更新后的 option，渲染图表
      myChart.setOption(options);
    });
  };

  return (
    <div
      ref={ref}
      className={['hzdz-direction-count', className].filter(Boolean).join(' ')}
      style={componentStyle}
      onClick={onClick}
      {...otherProps}
    >
      <div className="top-wrap">
        <div className="left-wrap">
          <div style={{backgroundImage: 'url(http://localhost:8085/static/images/xiaofanganquan/fire-alarm-number-icon.png)', width: '52px', height: '52px', backgroundSize: 'cover'}} />
          <div className="value-wrap">
            <div className="value">
              <div>57791</div>
              <span style={{fontSize: '12px', paddingBottom: '3px'}}>个</span>
            </div>
            <div className="name">告警数</div>
          </div>
        </div>
        <div className="chart-area">
          {/* 中间显示高亮的数据 */}
          {hoveredData && (
            <div className="hovered-data" style={{left: '27%'}}>
              <div className="hovered-value">{hoveredData.value}</div>
              <div>{hoveredData.name}</div>
            </div>
          )}

          <div className="chart-container"
               ref={chartContainerRef}
               style={{ height: '100%', width: '100%'}} />
          <div className="icon" style={{backgroundImage: actionIcon ? `url(${actionIcon})` : undefined, backgroundSize: 'cover'}} />
        </div>

      </div>
      <div className="bottom-wrap">
        <div className="left-wrap">
          <div style={{backgroundImage: 'url(http://localhost:8085/static/images/xiaofanganquan/fire-alarm-number-icon.png)', width: '52px', height: '52px', backgroundSize: 'cover'}} />
          <div className="value-wrap">
            <div className="name">告警分区数量</div>
          </div>
        </div>
        <div className="fx-wrap">
          <div className="fx_item">
            <div className="fx-name">西</div>
            <div className="value">
              <div>44</div>
              <span style={{fontSize: '12px', paddingBottom: '3px'}}>个</span>
            </div>
          </div>
          <div className="fx_item">
            <div className="fx-name">东</div>
            <div className="value">
              <div>129</div>
              <span style={{fontSize: '12px', paddingBottom: '3px'}}>个</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
});

DirectionCount.displayName = 'DirectionCount';

export default DirectionCount;
